Micron Document
🎖️GitЯра🎖️


Displaying Raw • Download

core/takserver/src/commonMain/kotlin/org/meshtastic/core/takserver/TAKClientConnection.kt 3c7e1266f819f90df2bfca6717cd1df0414d6c3a (3c7e1266) Text, 9.55 KB

T8b949e/*
* Copyright (c) 2026 Meshtastic LLC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
Tf0883e@fileTb4b4b4:Te6edf3SuppressTb4b4b4(Ta5d6ff"Ta5d6ffTooManyFunctionsTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffTooGenericExceptionCaughtTa5d6ff"Tb4b4b4)

Tff7b72package T7ee787org.meshtastic.core.takserver

Tff7b72import T7ee787co.touchlab.kermit.Logger
Tff7b72import T7ee787io.ktor.network.sockets.Socket
Tff7b72import T7ee787io.ktor.network.sockets.isClosed
Tff7b72import T7ee787io.ktor.network.sockets.openReadChannel
Tff7b72import T7ee787io.ktor.network.sockets.openWriteChannel
Tff7b72import T7ee787io.ktor.utils.io.ByteReadChannel
Tff7b72import T7ee787io.ktor.utils.io.ByteWriteChannel
Tff7b72import T7ee787io.ktor.utils.io.readAvailable
Tff7b72import T7ee787io.ktor.utils.io.writeStringUtf8
Tff7b72import T7ee787kotlinx.coroutines.CancellationException
Tff7b72import T7ee787kotlinx.coroutines.CoroutineScope
Tff7b72import T7ee787kotlinx.coroutines.launch
Tff7b72import T7ee787kotlinx.coroutines.sync.Mutex
Tff7b72import T7ee787kotlinx.coroutines.sync.withLock
Tff7b72import T7ee787kotlin.concurrent.Volatile
Tff7b72import T7ee787kotlin.random.Random
Tff7b72import T7ee787kotlin.time.Clock
Tff7b72import T7ee787kotlin.time.Duration.Companion.milliseconds
Tff7b72import T7ee787kotlin.time.Instant
Tff7b72import T7ee787kotlinx.coroutines.isActive Tff7b72as Te6edf3coroutineIsActive

Tff7b72class T56d364TAKClientConnectionTb4b4b4(
Tff7b72private Tff7b72val Te6edf3socketTb4b4b4: Te6edf3SocketTb4b4b4,
Tff7b72val Te6edf3clientInfoTb4b4b4: Te6edf3TAKClientInfoTb4b4b4,
Tff7b72private Tff7b72val Te6edf3onEventTb4b4b4: Tb4b4b4(Te6edf3TAKConnectionEventTb4b4b4) Tff7b72-Tff7b72> Tffa657UnitTb4b4b4,
Tff7b72private Tff7b72val Te6edf3scopeTb4b4b4: Te6edf3CoroutineScopeTb4b4b4,
Tb4b4b4) Tb4b4b4{
Tff7b72private Tff7b72var Te6edf3currentClientInfo Tff7b72= Te6edf3clientInfo
Tff7b72private Tff7b72val Te6edf3frameBuffer Tff7b72= Te6edf3CoTXmlFrameBufferTb4b4b4(Tb4b4b4)

Tff7b72private Tff7b72val Te6edf3readChannelTb4b4b4: Te6edf3ByteReadChannel Tff7b72= Te6edf3socketTb4b4b4.Te6edf3openReadChannelTb4b4b4(Tb4b4b4)
Tff7b72private Tff7b72val Te6edf3writeChannelTb4b4b4: Te6edf3ByteWriteChannel Tff7b72= Te6edf3socketTb4b4b4.Te6edf3openWriteChannelTb4b4b4(Te6edf3autoFlush Tff7b72= Tff7b72trueTb4b4b4)
Tff7b72private Tff7b72val Te6edf3writeMutex Tff7b72= Te6edf3MutexTb4b4b4(Tb4b4b4)

T8b949e/** Tracks the last time data was received from the client, used for idle timeout detection. */
Tf0883e@Volatile Tff7b72private Tff7b72var Te6edf3lastDataReceivedTb4b4b4: Te6edf3Instant Tff7b72= Te6edf3ClockTb4b4b4.Te6edf3SystemTb4b4b4.Te6edf3nowTb4b4b4(Tb4b4b4)

T8b949e/** Guards against emitting [TAKConnectionEvent.Disconnected] more than once. */
Tf0883e@Volatile Tff7b72private Tff7b72var Te6edf3disconnectedEmitted Tff7b72= Tff7b72false

Tff7b72fun Td2a8ffstartTb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3onEventTb4b4b4(Te6edf3TAKConnectionEventTb4b4b4.Te6edf3ConnectedTb4b4b4(Te6edf3currentClientInfoTb4b4b4)Tb4b4b4)
Te6edf3sendProtocolSupportTb4b4b4(Tb4b4b4)

Te6edf3scopeTb4b4b4.Te6edf3launch Tb4b4b4{ Te6edf3readLoopTb4b4b4(Tb4b4b4) Tb4b4b4}

Te6edf3scopeTb4b4b4.Te6edf3launch Tb4b4b4{ Te6edf3keepaliveLoopTb4b4b4(Tb4b4b4) Tb4b4b4}
Tb4b4b4}

Tff7b72private Tff7b72fun Td2a8ffsendProtocolSupportTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3serverUid Tff7b72= Ta5d6ff"Ta5d6ffMeshtastic-TAK-Server-Tffd700${Te6edf3RandomTb4b4b4.Te6edf3nextIntTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3toStringTb4b4b4(Te6edf3TAK_HEX_RADIXTb4b4b4)Tffd700}Ta5d6ff"
Tff7b72val Te6edf3now Tff7b72= Te6edf3ClockTb4b4b4.Te6edf3SystemTb4b4b4.Te6edf3nowTb4b4b4(Tb4b4b4)
Tff7b72val Te6edf3stale Tff7b72= Te6edf3now Tff7b72+ Te6edf3TAK_KEEPALIVE_INTERVAL_MSTb4b4b4.Te6edf3milliseconds
Tff7b72val Te6edf3detail Tff7b72=
Ta5d6ff"""
Ta5d6ff <TakControl>
<TakProtocolSupport version=Ta5d6ff"Ta5d6ff0Ta5d6ff"Ta5d6ff/>
</TakControl>
Ta5d6ff"""
Tb4b4b4.Te6edf3trimIndentTb4b4b4(Tb4b4b4)
Te6edf3sendXmlTb4b4b4(Te6edf3buildEventXmlTb4b4b4(Te6edf3uid Tff7b72= Te6edf3serverUidTb4b4b4, Te6edf3type Tff7b72= Ta5d6ff"Ta5d6fft-x-takp-vTa5d6ff"Tb4b4b4, Te6edf3now Tff7b72= Te6edf3nowTb4b4b4, Te6edf3stale Tff7b72= Te6edf3staleTb4b4b4, Te6edf3detail Tff7b72= Te6edf3detailTb4b4b4)Tb4b4b4)
Tb4b4b4}

Tff7b72private Tff7b72suspend Tff7b72fun Td2a8ffreadLoopTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72try Tb4b4b4{
Tff7b72val Te6edf3buffer Tff7b72= Te6edf3ByteArrayTb4b4b4(Te6edf3TAK_XML_READ_BUFFER_SIZETb4b4b4)
Tff7b72while Tb4b4b4(Te6edf3scopeTb4b4b4.Te6edf3coroutineIsActive Tff7b72&Tff7b72& Tff7b72!Te6edf3socketTb4b4b4.Te6edf3isClosedTb4b4b4) Tb4b4b4{
T8b949e// Suspend until data is available — no polling delay needed
Te6edf3readChannelTb4b4b4.Te6edf3awaitContentTb4b4b4(Tb4b4b4)
Tff7b72val Te6edf3bytesRead Tff7b72= Te6edf3readChannelTb4b4b4.Te6edf3readAvailableTb4b4b4(Te6edf3bufferTb4b4b4)
Tff7b72if Tb4b4b4(Te6edf3bytesRead Tff7b72> T79c0ff0Tb4b4b4) Tb4b4b4{
Te6edf3lastDataReceived Tff7b72= Te6edf3ClockTb4b4b4.Te6edf3SystemTb4b4b4.Te6edf3nowTb4b4b4(Tb4b4b4)
Te6edf3processReceivedDataTb4b4b4(Te6edf3bufferTb4b4b4.Te6edf3copyOfRangeTb4b4b4(T79c0ff0Tb4b4b4, Te6edf3bytesReadTb4b4b4)Tb4b4b4)
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3bytesRead Tff7b72=Tff7b72= Tff7b72-T79c0ff1Tb4b4b4) Tb4b4b4{
Tff7b72break T8b949e// EOF
Tb4b4b4}
Tb4b4b4}
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4: Te6edf3CancellationExceptionTb4b4b4) Tb4b4b4{
Tff7b72throw Te6edf3e
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4: Te6edf3ExceptionTb4b4b4) Tb4b4b4{
Te6edf3LoggerTb4b4b4.Te6edf3wTb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4{ Ta5d6ff"Ta5d6ffTAK client read error: Tffd700${Te6edf3currentClientInfoTb4b4b4.Te6edf3idTffd700}Ta5d6ff" Tb4b4b4}
Te6edf3emitDisconnectedTb4b4b4(Te6edf3TAKConnectionEventTb4b4b4.Te6edf3ErrorTb4b4b4(Te6edf3eTb4b4b4)Tb4b4b4)
Tff7b72return
Tb4b4b4}
Te6edf3emitDisconnectedTb4b4b4(Te6edf3TAKConnectionEventTb4b4b4.Te6edf3DisconnectedTb4b4b4)
Tb4b4b4}

Tff7b72private Tff7b72suspend Tff7b72fun Td2a8ffkeepaliveLoopTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3idleTimeoutMs Tff7b72= Te6edf3TAK_KEEPALIVE_INTERVAL_MS Tff7b72* Te6edf3TAK_READ_IDLE_TIMEOUT_MULTIPLIER
Tff7b72while Tb4b4b4(Te6edf3scopeTb4b4b4.Te6edf3coroutineIsActive Tff7b72&Tff7b72& Tff7b72!Te6edf3socketTb4b4b4.Te6edf3isClosedTb4b4b4) Tb4b4b4{
Te6edf3kotlinxTb4b4b4.Te6edf3coroutinesTb4b4b4.Te6edf3delayTb4b4b4(Te6edf3TAK_KEEPALIVE_INTERVAL_MSTb4b4b4)

Tff7b72val Te6edf3idleMs Tff7b72= Tb4b4b4(Te6edf3ClockTb4b4b4.Te6edf3SystemTb4b4b4.Te6edf3nowTb4b4b4(Tb4b4b4) Tff7b72- Te6edf3lastDataReceivedTb4b4b4)Tb4b4b4.Te6edf3inWholeMilliseconds
Tff7b72if Tb4b4b4(Te6edf3idleMs Tff7b72> Te6edf3idleTimeoutMsTb4b4b4) Tb4b4b4{
Te6edf3LoggerTb4b4b4.Te6edf3w Tb4b4b4{
Ta5d6ff"Ta5d6ffTAK client Tffd700${Te6edf3currentClientInfoTb4b4b4.Te6edf3idTffd700}Ta5d6ff idle for Tffd700${Te6edf3idleMsTffd700}Ta5d6ffms Ta5d6ff" Tff7b72+
Ta5d6ff"Ta5d6ff(threshold Tffd700${Te6edf3idleTimeoutMsTffd700}Ta5d6ffms), closing connectionTa5d6ff"
Tb4b4b4}
Te6edf3closeTb4b4b4(Tb4b4b4)
Tff7b72return
Tb4b4b4}

Te6edf3sendKeepaliveTb4b4b4(Tb4b4b4)
Tb4b4b4}
Tb4b4b4}

Tff7b72private Tff7b72fun Td2a8ffsendKeepaliveTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3now Tff7b72= Te6edf3ClockTb4b4b4.Te6edf3SystemTb4b4b4.Te6edf3nowTb4b4b4(Tb4b4b4)
Tff7b72val Te6edf3stale Tff7b72= Te6edf3now Tff7b72+ Tb4b4b4(Te6edf3TAK_KEEPALIVE_INTERVAL_MS Tff7b72* Te6edf3TAK_KEEPALIVE_STALE_MULTIPLIERTb4b4b4)Tb4b4b4.Te6edf3milliseconds
Te6edf3sendXmlTb4b4b4(Te6edf3buildEventXmlTb4b4b4(Te6edf3uid Tff7b72= Ta5d6ff"Ta5d6fftakPongTa5d6ff"Tb4b4b4, Te6edf3type Tff7b72= Ta5d6ff"Ta5d6fft-x-c-tTa5d6ff"Tb4b4b4, Te6edf3now Tff7b72= Te6edf3nowTb4b4b4, Te6edf3stale Tff7b72= Te6edf3staleTb4b4b4, Te6edf3detail Tff7b72= Ta5d6ff"Ta5d6ff"Tb4b4b4)Tb4b4b4)
Tb4b4b4}

Tff7b72private Tff7b72fun Td2a8ffsendPongTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3now Tff7b72= Te6edf3ClockTb4b4b4.Te6edf3SystemTb4b4b4.Te6edf3nowTb4b4b4(Tb4b4b4)
Tff7b72val Te6edf3stale Tff7b72= Te6edf3now Tff7b72+ Tb4b4b4(Te6edf3TAK_KEEPALIVE_INTERVAL_MS Tff7b72* Te6edf3TAK_KEEPALIVE_STALE_MULTIPLIERTb4b4b4)Tb4b4b4.Te6edf3milliseconds
Te6edf3sendXmlTb4b4b4(Te6edf3buildEventXmlTb4b4b4(Te6edf3uid Tff7b72= Ta5d6ff"Ta5d6fftakPongTa5d6ff"Tb4b4b4, Te6edf3type Tff7b72= Ta5d6ff"Ta5d6fft-x-c-t-rTa5d6ff"Tb4b4b4, Te6edf3now Tff7b72= Te6edf3nowTb4b4b4, Te6edf3stale Tff7b72= Te6edf3staleTb4b4b4, Te6edf3detail Tff7b72= Ta5d6ff"Ta5d6ff"Tb4b4b4)Tb4b4b4)
Tb4b4b4}

Tff7b72private Tff7b72fun Td2a8ffprocessReceivedDataTb4b4b4(Te6edf3newDataTb4b4b4: Te6edf3ByteArrayTb4b4b4) Tb4b4b4{
T8b949e// frameBuffer.append returns List<String> — pass directly without re-encoding
Te6edf3frameBufferTb4b4b4.Te6edf3appendTb4b4b4(Te6edf3newDataTb4b4b4)Tb4b4b4.Te6edf3forEach Tb4b4b4{ Te6edf3xmlString Tff7b72-Tff7b72> Te6edf3parseAndHandleMessageTb4b4b4(Te6edf3xmlStringTb4b4b4) Tb4b4b4}
Tb4b4b4}

Tff7b72private Tff7b72fun Td2a8ffparseAndHandleMessageTb4b4b4(Te6edf3xmlStringTb4b4b4: Tffa657StringTb4b4b4) Tb4b4b4{
T8b949e// Parse first, then filter on the structured type field to avoid false positives
Tff7b72val Te6edf3parser Tff7b72= Te6edf3CoTXmlParserTb4b4b4(Te6edf3xmlStringTb4b4b4)
Tff7b72val Te6edf3result Tff7b72= Te6edf3parserTb4b4b4.Te6edf3parseTb4b4b4(Tb4b4b4)

Te6edf3resultTb4b4b4.Te6edf3onSuccess Tb4b4b4{ Te6edf3cotMessage Tff7b72-Tff7b72>
Tff7b72when Tb4b4b4{
Te6edf3cotMessageTb4b4b4.Te6edf3typeTb4b4b4.Te6edf3startsWithTb4b4b4(Ta5d6ff"Ta5d6fft-x-takpTa5d6ff"Tb4b4b4) Tff7b72-Tff7b72> Tb4b4b4{
Te6edf3handleProtocolControlTb4b4b4(Te6edf3cotMessageTb4b4b4.Te6edf3typeTb4b4b4, Te6edf3xmlStringTb4b4b4)
Tff7b72return
Tb4b4b4}
Te6edf3cotMessageTb4b4b4.Te6edf3type Tff7b72=Tff7b72= Ta5d6ff"Ta5d6fft-x-c-tTa5d6ff" Tff7b72|Tff7b72| Te6edf3cotMessageTb4b4b4.Te6edf3uid Tff7b72=Tff7b72= Ta5d6ff"Ta5d6ffpingTa5d6ff" Tff7b72-Tff7b72> Tb4b4b4{
Te6edf3sendPongTb4b4b4(Tb4b4b4)
Tff7b72return
Tb4b4b4}
Tff7b72else Tff7b72-Tff7b72> Tb4b4b4{
Te6edf3cotMessageTb4b4b4.Te6edf3contactTff7b72?.Te6edf3let Tb4b4b4{ Te6edf3contact Tff7b72-Tff7b72>
Tff7b72val Te6edf3updatedClientInfo Tff7b72=
Te6edf3currentClientInfoTb4b4b4.Te6edf3copyTb4b4b4(
Te6edf3callsign Tff7b72= Te6edf3currentClientInfoTb4b4b4.Te6edf3callsign Tff7b72?: Te6edf3contactTb4b4b4.Te6edf3callsignTb4b4b4,
Te6edf3uid Tff7b72= Te6edf3currentClientInfoTb4b4b4.Te6edf3uid Tff7b72?: Te6edf3cotMessageTb4b4b4.Te6edf3uidTb4b4b4,
Tb4b4b4)
Tff7b72if Tb4b4b4(Te6edf3updatedClientInfo Tff7b72!Tff7b72= Te6edf3currentClientInfoTb4b4b4) Tb4b4b4{
Te6edf3currentClientInfo Tff7b72= Te6edf3updatedClientInfo
Te6edf3onEventTb4b4b4(Te6edf3TAKConnectionEventTb4b4b4.Te6edf3ClientInfoUpdatedTb4b4b4(Te6edf3updatedClientInfoTb4b4b4)Tb4b4b4)
Tb4b4b4}
Tb4b4b4}

Te6edf3onEventTb4b4b4(Te6edf3TAKConnectionEventTb4b4b4.Te6edf3MessageTb4b4b4(Te6edf3cotMessageTb4b4b4)Tb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}

Tff7b72private Tff7b72fun Td2a8ffhandleProtocolControlTb4b4b4(Te6edf3typeTb4b4b4: Tffa657StringTb4b4b4, Te6edf3xmlStringTb4b4b4: Tffa657StringTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3type Tff7b72=Tff7b72= Ta5d6ff"Ta5d6fft-x-takp-qTa5d6ff"Tb4b4b4) Tb4b4b4{
Te6edf3sendProtocolResponseTb4b4b4(Tb4b4b4)
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3LoggerTb4b4b4.Te6edf3d Tb4b4b4{ Ta5d6ff"Ta5d6ffUnhandled protocol control type: Tffd700$Te6edf3typeTa5d6ff (raw=Tffd700$Te6edf3xmlStringTa5d6ff)Ta5d6ff" Tb4b4b4}
Tb4b4b4}
Tb4b4b4}

Tff7b72private Tff7b72fun Td2a8ffsendProtocolResponseTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3serverUid Tff7b72= Ta5d6ff"Ta5d6ffMeshtastic-TAK-Server-Tffd700${Te6edf3RandomTb4b4b4.Te6edf3nextIntTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3toStringTb4b4b4(Te6edf3TAK_HEX_RADIXTb4b4b4)Tffd700}Ta5d6ff"
Tff7b72val Te6edf3now Tff7b72= Te6edf3ClockTb4b4b4.Te6edf3SystemTb4b4b4.Te6edf3nowTb4b4b4(Tb4b4b4)
Tff7b72val Te6edf3stale Tff7b72= Te6edf3now Tff7b72+ Te6edf3TAK_KEEPALIVE_INTERVAL_MSTb4b4b4.Te6edf3milliseconds
Tff7b72val Te6edf3detail Tff7b72=
Ta5d6ff"""
Ta5d6ff <TakControl>
<TakResponse status=Ta5d6ff"Ta5d6fftrueTa5d6ff"Ta5d6ff/>
</TakControl>
Ta5d6ff"""
Tb4b4b4.Te6edf3trimIndentTb4b4b4(Tb4b4b4)
Te6edf3sendXmlTb4b4b4(Te6edf3buildEventXmlTb4b4b4(Te6edf3uid Tff7b72= Te6edf3serverUidTb4b4b4, Te6edf3type Tff7b72= Ta5d6ff"Ta5d6fft-x-takp-rTa5d6ff"Tb4b4b4, Te6edf3now Tff7b72= Te6edf3nowTb4b4b4, Te6edf3stale Tff7b72= Te6edf3staleTb4b4b4, Te6edf3detail Tff7b72= Te6edf3detailTb4b4b4)Tb4b4b4)
Tb4b4b4}

Tff7b72fun Td2a8ffsendTb4b4b4(Te6edf3cotMessageTb4b4b4: Te6edf3CoTMessageTb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3xml Tff7b72= Te6edf3cotMessageTb4b4b4.Te6edf3toXmlTb4b4b4(Tb4b4b4)
Te6edf3sendXmlTb4b4b4(Te6edf3xmlTb4b4b4)
Tb4b4b4}

Tff7b72private Tff7b72fun Td2a8ffbuildEventXmlTb4b4b4(Te6edf3uidTb4b4b4: Tffa657StringTb4b4b4, Te6edf3typeTb4b4b4: Tffa657StringTb4b4b4, Te6edf3nowTb4b4b4: Te6edf3InstantTb4b4b4, Te6edf3staleTb4b4b4: Te6edf3InstantTb4b4b4, Te6edf3detailTb4b4b4: Tffa657StringTb4b4b4)Tb4b4b4: Tffa657String Tb4b4b4{
Tff7b72val Te6edf3detailContent Tff7b72= Tff7b72if Tb4b4b4(Te6edf3detailTb4b4b4.Te6edf3isBlankTb4b4b4(Tb4b4b4)Tb4b4b4) Ta5d6ff"Ta5d6ff<detail/>Ta5d6ff" Tff7b72else Ta5d6ff"Ta5d6ff<detail>Tffd700$Te6edf3detailTa5d6ff</detail>Ta5d6ff"
Tff7b72val Te6edf3point Tff7b72= Ta5d6ff"""Ta5d6ff<point lat=Ta5d6ff"Ta5d6ff0Ta5d6ff"Ta5d6ff lon=Ta5d6ff"Ta5d6ff0Ta5d6ff"Ta5d6ff hae=Ta5d6ff"Ta5d6ff0Ta5d6ff"Ta5d6ff ce=Ta5d6ff"Tffd700$Te6edf3TAK_UNKNOWN_POINT_VALUETa5d6ff"Ta5d6ff le=Ta5d6ff"Tffd700$Te6edf3TAK_UNKNOWN_POINT_VALUETa5d6ff"Ta5d6ff/>Ta5d6ff"""
Tff7b72return Ta5d6ff"""Ta5d6ff<event version=Ta5d6ff"Ta5d6ff2.0Ta5d6ff"Ta5d6ff uid=Ta5d6ff"Tffd700$Te6edf3uidTa5d6ff"Ta5d6ff type=Ta5d6ff"Tffd700$Te6edf3typeTa5d6ff"Ta5d6ff time=Ta5d6ff"Tffd700$Te6edf3nowTa5d6ff"Ta5d6ff start=Ta5d6ff"Tffd700$Te6edf3nowTa5d6ff"Ta5d6ff stale=Ta5d6ff"Tffd700$Te6edf3staleTa5d6ff"Ta5d6ff how=Ta5d6ff"Ta5d6ffm-gTa5d6ff"Ta5d6ff>Ta5d6ff""" Tff7b72+
Te6edf3point Tff7b72+
Te6edf3detailContent Tff7b72+
Ta5d6ff"Ta5d6ff</event>Ta5d6ff"
Tb4b4b4}

Tff7b72private Tff7b72fun Td2a8ffsendXmlTb4b4b4(Te6edf3xmlTb4b4b4: Tffa657StringTb4b4b4) Tb4b4b4{
Te6edf3scopeTb4b4b4.Te6edf3launch Tb4b4b4{
Tff7b72try Tb4b4b4{
Te6edf3writeMutexTb4b4b4.Te6edf3withLock Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3socketTb4b4b4.Te6edf3isClosedTb4b4b4) Tb4b4b4{
Te6edf3writeChannelTb4b4b4.Te6edf3writeStringUtf8Tb4b4b4(Te6edf3xmlTb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4: Te6edf3CancellationExceptionTb4b4b4) Tb4b4b4{
Tff7b72throw Te6edf3e
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4: Te6edf3ExceptionTb4b4b4) Tb4b4b4{
Te6edf3LoggerTb4b4b4.Te6edf3wTb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4{ Ta5d6ff"Ta5d6ffTAK client send error: Tffd700${Te6edf3currentClientInfoTb4b4b4.Te6edf3idTffd700}Ta5d6ff" Tb4b4b4}
Te6edf3closeTb4b4b4(Tb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}

Tff7b72fun Td2a8ffcloseTb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3frameBufferTb4b4b4.Te6edf3clearTb4b4b4(Tb4b4b4)
Tff7b72try Tb4b4b4{
Te6edf3socketTb4b4b4.Te6edf3closeTb4b4b4(Tb4b4b4)
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4: Te6edf3ExceptionTb4b4b4) Tb4b4b4{
Te6edf3LoggerTb4b4b4.Te6edf3wTb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4{ Ta5d6ff"Ta5d6ffError closing TAK client socket: Tffd700${Te6edf3currentClientInfoTb4b4b4.Te6edf3idTffd700}Ta5d6ff" Tb4b4b4}
Tb4b4b4}
Te6edf3emitDisconnectedTb4b4b4(Te6edf3TAKConnectionEventTb4b4b4.Te6edf3DisconnectedTb4b4b4)
Tb4b4b4}

T8b949e/**
* Emits [event] (expected to be [TAKConnectionEvent.Disconnected] or [TAKConnectionEvent.Error]) at most once
* across all code paths.
*/
Tff7b72private Tff7b72fun Td2a8ffemitDisconnectedTb4b4b4(Te6edf3eventTb4b4b4: Te6edf3TAKConnectionEventTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3disconnectedEmittedTb4b4b4) Tb4b4b4{
Te6edf3disconnectedEmitted Tff7b72= Tff7b72true
Te6edf3onEventTb4b4b4(Te6edf3eventTb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}

Served by rngit 1.5.4 - Generated in 0.05s